import { Injectable, Logger } from '@nestjs/common';
import { Common } from '../common/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository, SelectQueryBuilder, UpdateResult } from 'typeorm';
import { Candidates } from '../../module/Candidates';
import {
  CandidateInterface,
  CandidateUpdInterface,
  QueryCandidateInterface,
} from './interface/candidate.interface';
import * as moment from 'moment';
import { ElectionSettings } from '../../module/ElectionSettings';
import Redis from 'ioredis';
import { RedisService } from '@liaoliaots/nestjs-redis';
import { RedisConfig } from '../../@nt/config';

@Injectable()
export class CandidateService extends Common {
  private readonly logger = new Logger(CandidateService.name);
  private readonly redis: Redis | null;

  constructor(
    @InjectRepository(Candidates)
    private readonly candidateRepository: Repository<Candidates>,
    @InjectRepository(ElectionSettings)
    private readonly electionSettingsRepository: Repository<ElectionSettings>,
    private readonly redisService: RedisService,
  ) {
    super();
    this.redis = this.redisService.getOrThrow();
  }

  /**
   * 创建候选人
   * @param body
   */
  async create(body: CandidateInterface): Promise<any> {
    const where: any = { name: body.name };
    let candidate = await this.candidateRepository.findOne({ where });
    if (candidate) {
      return this.returnJson(4003, candidate, '候选人已存在，请勿重复添加');
    }
    const data: any = {
      name: body.name,
      gender: body.gender,
      createdAt: moment().unix(),
    };
    candidate = await this.candidateRepository.save(data);
    if (candidate) {
      this.candidateRedisInit(candidate);
      return this.returnJson(0, candidate, '成功');
    }
    return this.returnJson(-1, false, '失败');
  }

  /**
   * 获取候选人列表
   * @param query
   */
  async findAll(query: QueryCandidateInterface): Promise<any> {
    const where: any = {};
    if (query.name) {
      where.name = Like(`%${query.name}%`);
    }
    if (query.gender) {
      where.gender = query.gender;
    }
    if (query.status) {
      where.status = query.status;
    }
    const limit: number = query.pageSize || 100;
    const offset: number = (query.pageNo - 1) * limit;
    const repository: SelectQueryBuilder<Candidates> =
      this.candidateRepository.createQueryBuilder('candidate');
    const totalCount: number = await repository.where(where).getCount();
    const result = await repository
      .select('candidate.*')
      .where(where)
      .orderBy('id', 'DESC')
      .limit(limit)
      .offset(offset)
      .getRawMany();
    return this.returnJson(
      0,
      this.returnPage(query.pageNo, totalCount, result),
    );
  }

  /**
   * 根据ID获取候选人信息
   * @param id
   */
  async findOne(id: number): Promise<any> {
    const where: any = { id };
    const candidateInfo: Candidates = await this.candidateRepository.findOne({
      where,
    });
    if (!candidateInfo) {
      return this.returnJson(4004, false, '候选人不存在');
    }
    return this.returnJson(0, candidateInfo, '成功');
  }

  /**
   * 更新候选人信息
   * @param id
   * @param body
   */
  async update(id: number, body: CandidateUpdInterface): Promise<any> {
    const where: any = { id };
    const candidateInfo: Candidates = await this.candidateRepository.findOne({
      where,
    });
    if (!candidateInfo) {
      return this.returnJson(4004, false, '候选人不存在');
    }
    const setWhere: any = { isActive: 1 };
    const electionSettingInfo: ElectionSettings =
      await this.electionSettingsRepository.findOne({ where: setWhere });
    if (electionSettingInfo) {
      if (
        moment().unix() > electionSettingInfo.startTime &&
        moment().unix() < electionSettingInfo.endTime
      ) {
        return this.returnJson(4005, false, '选举进行中，禁止修改候选人信息');
      }
    }
    const data: any = {
      updatedAt: moment().unix(),
    };
    if (body.name) {
      data.name = body.name;
    }
    if (body.gender) {
      data.gender = body.gender;
    }
    if (body.status) {
      data.status = body.status;
    }
    const result: UpdateResult = await this.candidateRepository.update(
      where,
      data,
    );
    if (result.affected) {
      this.candidateRedisInit(candidateInfo);
      return this.returnJson(0, true, '成功');
    }
    return this.returnJson(-1, false, '失败');
  }

  /**
   * 候选人Redis初始化
   * @param candidateInfo
   */
  candidateRedisInit(candidateInfo: Candidates) {
    if (candidateInfo.status) {
      this.redis.incr(RedisConfig.electionTotal);
      this.redis.hset(RedisConfig.electionCandidateVotes, candidateInfo.id, 0);
    }
  }
}
